package cn.iocoder.yudao.module.system.service.wishlist;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.controller.admin.wishlist.vo.UserWishListCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.wishlist.vo.UserWishListPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.wishlist.vo.UserWishListRespVO;
import cn.iocoder.yudao.module.system.controller.admin.wishlist.vo.UserWishListUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.wishlist.vo.UserWishListWithScoreRespVO;
import cn.iocoder.yudao.module.system.convert.wishlist.UserWishListConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.wishlist.UserWishListDO;
import cn.iocoder.yudao.module.system.dal.mysql.wishlist.UserWishListMapper;
import cn.iocoder.yudao.module.system.service.user.UserScoresService;
import cn.iocoder.yudao.module.system.dal.dataobject.user.UserScoresDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;

/**
 * 用户志愿表 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Slf4j
public class UserWishListServiceImpl implements UserWishListService {

    @Resource
    private UserWishListMapper userWishListMapper;

    @Resource
    private FileApi fileApi;

    @Resource
    private UserScoresService userScoresService;

    @Override
    public Long createUserWishList(@Valid UserWishListCreateReqVO createReqVO, Long userId) {


        // 插入
        UserWishListDO userWishList = UserWishListConvert.INSTANCE.convert(createReqVO);
        userWishList.setUserId(userId);

        // 如果没有指定志愿顺序，则自动设置为该类型的最后一个
        if (userWishList.getWishOrder() == null) {
            Long count = getWishListCountByUserIdAndWishType(userId, createReqVO.getWishType());
            userWishList.setWishOrder(count.intValue() + 1);
        }

        // 验证并关联成绩记录
        if (userWishList.getUserScoreId() == null) {
            // 如果没有指定成绩记录ID，尝试自动关联当前用户的成绩记录
            UserScoresDO currentUserScore = userScoresService.getCurrentUserScore(userId);
            if (currentUserScore != null) {
                userWishList.setUserScoreId(currentUserScore.getId());
                log.info("[createUserWishList][用户{}自动关联成绩记录ID={}]", userId, currentUserScore.getId());
            } else {
                // 没有找到有效的成绩记录，抛出异常
                throw exception(USER_SCORES_REQUIRED);
            }
        } else {
            // 如果指定了成绩记录ID，使用统一的验证方法
            validateUserScore(userWishList.getUserScoreId(), userId);
        }

        userWishListMapper.insert(userWishList);

        log.info("[createUserWishList][用户{}添加志愿成功，志愿ID={}]", userId, userWishList.getId());
        return userWishList.getId();
    }

    @Override
    public void updateUserWishList(@Valid UserWishListUpdateReqVO updateReqVO, Long userId) {
        // 校验存在
        UserWishListDO existingWishList = validateUserWishListExists(updateReqVO.getId(), userId);
        
        // 检查是否修改了关键信息，如果修改了需要检查重复
        if (!existingWishList.getSchoolUuid().equals(updateReqVO.getSchoolUuid()) ||
            !existingWishList.getMajorName().equals(updateReqVO.getMajorName()) ||
            !existingWishList.getYear().equals(updateReqVO.getYear())) {
            
            if (isWishListExists(userId, updateReqVO.getSchoolUuid(), updateReqVO.getMajorName(), updateReqVO.getYear())) {
                throw exception(USER_WISH_LIST_EXISTS);
            }
        }

        // 更新
        UserWishListDO updateObj = UserWishListConvert.INSTANCE.convert(updateReqVO);
        updateObj.setUserId(userId);
        
        // 验证并关联成绩记录
        if (updateObj.getUserScoreId() == null) {
            // 如果没有指定成绩记录ID，尝试自动关联当前用户的成绩记录
            UserScoresDO currentScore = userScoresService.getCurrentUserScore(userId);
            if (currentScore != null) {
                updateObj.setUserScoreId(currentScore.getId());
                log.info("[updateUserWishList][用户{}自动关联成绩记录ID={}]", userId, currentScore.getId());
            } else {
                // 没有找到有效的成绩记录，抛出异常
                throw exception(USER_SCORES_REQUIRED);
            }
        } else {
            // 如果指定了成绩记录ID，使用统一的验证方法
            validateUserScore(updateObj.getUserScoreId(), userId);
        }
        
        userWishListMapper.updateById(updateObj);
        
        log.info("[updateUserWishList][用户{}更新志愿成功，志愿ID={}]", userId, updateReqVO.getId());
    }

    @Override
    public void deleteUserWishList(Long id, Long userId) {
        // 校验存在
        validateUserWishListExists(id, userId);
        // 删除
        userWishListMapper.deleteById(id);
        
        log.info("[deleteUserWishList][用户{}删除志愿成功，志愿ID={}]", userId, id);
    }

    private UserWishListDO validateUserWishListExists(Long id, Long userId) {
        UserWishListDO userWishList = getUserWishList(id, userId);
        if (userWishList == null) {
            throw exception(USER_WISH_LIST_NOT_EXISTS);
        }
        return userWishList;
    }

    @Override
    public UserWishListDO getUserWishList(Long id, Long userId) {
        UserWishListDO userWishList = userWishListMapper.selectById(id);
        if (userWishList != null && !userWishList.getUserId().equals(userId)) {
            return null; // 不是当前用户的志愿，返回null
        }
        return userWishList;
    }

    @Override
    public PageResult<UserWishListDO> getUserWishListPage(UserWishListPageReqVO pageReqVO) {
        return userWishListMapper.selectPage(pageReqVO);
    }

    @Override
    public List<UserWishListDO> getUserWishListByUserId(Long userId) {
        return userWishListMapper.selectListByUserId(userId);
    }

    @Override
    public List<UserWishListDO> getUserWishListByUserIdAndWishType(Long userId, String wishType) {
        return userWishListMapper.selectListByUserIdAndWishType(userId, wishType);
    }

    @Override
    public boolean isWishListExists(Long userId, String schoolUuid, String majorName, Integer year) {
        UserWishListDO existing = userWishListMapper.selectByUserIdAndSchoolAndMajor(userId, schoolUuid, majorName, year);
        return existing != null;
    }

    @Override
    public void updateWishOrder(Long userId, String wishType, List<Long> wishListIds) {
        for (int i = 0; i < wishListIds.size(); i++) {
            Long wishListId = wishListIds.get(i);
            UserWishListDO userWishList = validateUserWishListExists(wishListId, userId);
            
            // 检查志愿类型是否匹配
            if (!wishType.equals(userWishList.getWishType())) {
                throw exception(USER_WISH_LIST_TYPE_MISMATCH);
            }
            
            // 更新顺序
            UserWishListDO updateObj = new UserWishListDO();
            updateObj.setId(wishListId);
            updateObj.setWishOrder(i + 1);
            userWishListMapper.updateById(updateObj);
        }
        
        log.info("[updateWishOrder][用户{}更新{}类型志愿顺序成功]", userId, wishType);
    }

    @Override
    public Long getWishListCountByUserIdAndWishType(Long userId, String wishType) {
        return userWishListMapper.selectCountByUserIdAndWishType(userId, wishType);
    }

    @Override
    public boolean checkAndClearWishListIfUserInfoChanged(Long userId, String userProvince, Integer userTotalScore,
                                                          String userSubjectSelection, Integer userYear) {
        // 获取用户的第一个志愿记录，用于比较用户基本信息
        UserWishListDO firstWishList = userWishListMapper.selectFirstByUserId(userId);

        // 如果用户没有任何志愿记录，则不需要检测
        if (firstWishList == null) {
            return false;
        }

        // 检测用户基本信息是否发生变更
        boolean provinceChanged = !Objects.equals(firstWishList.getUserProvince(), userProvince);
        boolean scoreChanged = !Objects.equals(firstWishList.getUserTotalScore(), userTotalScore);
        boolean subjectChanged = !Objects.equals(firstWishList.getUserSubjectSelection(), userSubjectSelection);
        boolean yearChanged = !Objects.equals(firstWishList.getUserYear(), userYear);

        // 如果任何一项基本信息发生变更，则清空用户的所有志愿
        if (provinceChanged || scoreChanged || subjectChanged || yearChanged) {
            log.info("[checkAndClearWishListIfUserInfoChanged][用户{}基本信息发生变更] 省份变更:{}, 分数变更:{}, 选科变更:{}, 年份变更:{}",
                    userId, provinceChanged, scoreChanged, subjectChanged, yearChanged);

            // 记录变更详情
            if (provinceChanged) {
                log.info("[checkAndClearWishListIfUserInfoChanged][用户{}] 省份从 {} 变更为 {}",
                        userId, firstWishList.getUserProvince(), userProvince);
            }
            if (scoreChanged) {
                log.info("[checkAndClearWishListIfUserInfoChanged][用户{}] 分数从 {} 变更为 {}",
                        userId, firstWishList.getUserTotalScore(), userTotalScore);
            }
            if (subjectChanged) {
                log.info("[checkAndClearWishListIfUserInfoChanged][用户{}] 选科从 {} 变更为 {}",
                        userId, firstWishList.getUserSubjectSelection(), userSubjectSelection);
            }
            if (yearChanged) {
                log.info("[checkAndClearWishListIfUserInfoChanged][用户{}] 年份从 {} 变更为 {}",
                        userId, firstWishList.getUserYear(), userYear);
            }

            // 清空用户的所有志愿记录
            int deletedCount = userWishListMapper.deleteByUserId(userId);
            log.info("[checkAndClearWishListIfUserInfoChanged][用户{}] 已清空 {} 条志愿记录", userId, deletedCount);

            return true;
        }

        return false;
    }

    @Override
    public Long getWishListCountByUserIdAndConditions(Long userId, String userProvince, String userSubjectSelection, Integer userTotalScore) {
        return userWishListMapper.selectCountByUserIdAndConditions(userId, userProvince, userSubjectSelection, userTotalScore);
    }

    @Override
    public String exportUserWishListToFile(UserWishListPageReqVO pageReqVO, Long userId) {
        try {
            // 设置用户ID和无分页限制
            pageReqVO.setUserId(userId);
            pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);

            // 获取用户志愿表数据
            List<UserWishListDO> list = userWishListMapper.selectPage(pageReqVO).getList();

            // 转换为响应VO
            List<UserWishListRespVO> dataList = UserWishListConvert.INSTANCE.convertList(list);

            // 生成Excel文件内容
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            EasyExcel.write(outputStream, UserWishListRespVO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度，自动适配
                    .registerWriteHandler(new SelectSheetWriteHandler(UserWishListRespVO.class)) // 基于固定 sheet 实现下拉框
                    .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
                    .sheet("志愿数据")
                    .doWrite(dataList);

            byte[] content = outputStream.toByteArray();
            outputStream.close();

            // 生成文件名（包含时间戳）
            String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
            String fileName = String.format("用户志愿表_%s.xlsx", timestamp);

            // 上传文件到文件服务
            String fileUrl = fileApi.createFile(fileName, null, content);

            log.info("[exportUserWishListToFile][用户{}导出志愿表成功，文件URL={}]", userId, fileUrl);
            return fileUrl;

        } catch (IOException e) {
            log.error("[exportUserWishListToFile][用户{}导出志愿表失败]", userId, e);
            throw new RuntimeException("导出志愿表失败", e);
        }
    }

    @Override
    public UserWishListWithScoreRespVO getUserWishListWithScore(Long id, Long userId) {
        // 获取志愿表记录
        UserWishListDO wishList = getUserWishList(id, userId);
        if (wishList == null) {
            return null;
        }

        // 获取关联的成绩记录
        UserScoresDO userScore = null;
        if (wishList.getUserScoreId() != null) {
            userScore = userScoresService.getUserScores(wishList.getUserScoreId());
        }

        // 转换为包含成绩信息的响应VO
        return UserWishListConvert.INSTANCE.convertWithScore(wishList, userScore);
    }

    @Override
    public List<UserWishListWithScoreRespVO> getUserWishListWithScoreByUserId(Long userId) {
        // 获取用户的所有志愿表记录
        List<UserWishListDO> wishLists = getUserWishListByUserId(userId);
        if (wishLists.isEmpty()) {
            return List.of();
        }

        // 批量获取关联的成绩记录
        List<UserWishListWithScoreRespVO> result = new ArrayList<>();
        for (UserWishListDO wishList : wishLists) {
            UserScoresDO userScore = null;
            if (wishList.getUserScoreId() != null) {
                userScore = userScoresService.getUserScores(wishList.getUserScoreId());
            }
            result.add(UserWishListConvert.INSTANCE.convertWithScore(wishList, userScore));
        }

        return result;
    }

    @Override
    public PageResult<UserWishListWithScoreRespVO> getUserWishListWithScorePage(UserWishListPageReqVO pageReqVO) {
        // 获取分页的志愿表记录
        PageResult<UserWishListDO> pageResult = getUserWishListPage(pageReqVO);
        if (pageResult.getList().isEmpty()) {
            return PageResult.empty(pageResult.getTotal());
        }

        // 批量获取关联的成绩记录并转换
        List<UserWishListWithScoreRespVO> resultList = new ArrayList<>();
        for (UserWishListDO wishList : pageResult.getList()) {
            UserScoresDO userScore = null;
            if (wishList.getUserScoreId() != null) {
                userScore = userScoresService.getUserScores(wishList.getUserScoreId());
            }
            resultList.add(UserWishListConvert.INSTANCE.convertWithScore(wishList, userScore));
        }

        return new PageResult<>(resultList, pageResult.getTotal());
    }

    @Override
    public UserScoresDO validateUserScore(Long userScoreId, Long userId) {
        if (userScoreId == null) {
            throw exception(USER_SCORES_REQUIRED);
        }
        
        // 获取成绩记录
        UserScoresDO userScore = userScoresService.getUserScores(userScoreId);
        if (userScore == null) {
            throw exception(USER_SCORES_NOT_EXISTS);
        }
        
        // 验证成绩记录是否属于当前用户
        if (!userScore.getUserId().equals(userId)) {
            throw exception(USER_SCORES_INVALID);
        }
        
        return userScore;
    }

}
